package org.chipu.jnids.sancp;

import java.io.File;
import java.io.FilenameFilter;
import java.util.*;
import org.chipu.jnids.beans.Flow;
import org.chipu.jnids.beans.Snapshot;
import org.chipu.shared.util.singletons.LoggingUtils;

public class SnapShotCreator {
	private final File sancpDataDir;
	private static final Comparator<File> fileNameComparator = new Comparator<File>() {
		@Override
		public int compare(File o1, File o2) {
			return o1.getName().compareTo(o2.getName());
		}
	};

	public SnapShotCreator(File sancpLogDir) {
		if (sancpLogDir == null)
			throw new NullPointerException();
		sancpDataDir = sancpLogDir;
	}

	/** Detect which files the snapshot should use. */
	public Snapshot createSnapshot() {
		if (!sancpDataDir.isDirectory())
			throw new IllegalStateException("The abstract pathname does not denote a directory: "
				+ sancpDataDir.getAbsolutePath());
		List<File> realtimeLogs = Arrays.asList(sancpDataDir.listFiles(new FilenameFilter() {
			@Override
			public boolean accept(File dir, String name) {
				return name.startsWith("realtime.");
			}
		}));
		List<File> statsLogs = Arrays.asList(sancpDataDir.listFiles(new FilenameFilter() {
			@Override
			public boolean accept(File dir, String name) {
				return name.startsWith("stats.");
			}
		}));
		if (realtimeLogs.isEmpty() || statsLogs.isEmpty())
			throw new IllegalStateException("There are no enough files to fullfill the request in "
				+ sancpDataDir.getAbsolutePath() + ".\n\t" + realtimeLogs + "\n\t" + statsLogs);
		Collections.sort(realtimeLogs, fileNameComparator);
		Collections.sort(statsLogs, fileNameComparator);
		return createSnapshot(realtimeLogs, statsLogs);
	}

	// FIXME si los archivos son muy grandes, hacer búsquedas binarias para descargar la mayor parte de los datos
	private synchronized Snapshot createSnapshot(Iterable<File> realtimeFiles, Iterable<File> statFiles) {
		try {
			Set<Flow> openedConnections = new HashSet<Flow>();
			Set<Flow> closedConnections = new HashSet<Flow>();
			for(File f : realtimeFiles)
				openedConnections.addAll(NetFlowReader.getInstance().retrieveFlows(f, "realtime"));
			for(File f : statFiles)
				closedConnections.addAll(NetFlowReader.getInstance().retrieveFlows(f, "stats"));
			LoggingUtils.getLogger().finest(
				"Closed connections: " + closedConnections.size() + ".  Opened connections: " + openedConnections.size());
			openedConnections.removeAll(closedConnections);
			return new Snapshot((int) (System.currentTimeMillis() / 1000), openedConnections);
		} catch(Exception ex) {
			ex.printStackTrace();
		}
		return new Snapshot((int) (System.currentTimeMillis() / 1000));
	}
}